package org.as3search.criteria {
	/*
	 * as3search - http://code.google.com/p/as3search
	 * Copyright (c) 2009-2010 by respective authors. All rights reserved.
	 *
	 * This library is free software; you can redistribute it and/or modify it under the
	 * terms of the GNU Lesser General Public License as published by the Free Software
	 * Foundation; either version 2.1 of the License, or (at your option) any later
	 * version.
	 *
	 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
	 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
	 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
	 *
	 * You should have received a copy of the GNU Lesser General Public License along
	 * with this library; if not, write to the Free Software Foundation, Inc.,
	 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
	 */
	
	import org.as3search.config.SearchConfiguration;

	/**
	 * A <code>Criteria</code> instance is the main unit of modularity 
	 * in as3search. A <code>Criteria</code> implementation is responsible
	 * for adding and evaluating multiple <code>Criterion</code> instances
	 * against a <code>SearchProvider</code> to search through an entire
	 * collection. An implementation is also responsible for creating and
	 * maintaining subcriteria for searching through subcollections and
	 * evaluating multiple <code>Criterion</code> instances against each
	 * item in a subcollection. <br/><br/>
	 * 
	 * <code>Criteria</code> is also responsible for returning results
	 * and evaluating tests against the collection, allowing users to 
	 * return their results. Each <code>Criteria</code> instance is 
	 * tethered to its own <code>SearchConfiguration</code> and 
	 * <code>SearchProvider</code> allowing infinite possibilities for
	 * a developer to create and customize their own configurations
	 * and create criteria queries on collections in any way they choose.
	 * 
	 * @see org.as3search.criteria.Criterion
	 * @see org.as3search.criteria.Restrictions
	 * @see org.as3search.criteria.impl.CriteriaImpl
	 * @see org.as3search.config.SearchConfiguration
	 * @see org.as3search.providers.SearchProvider
	 */
	public interface Criteria {
		/**
		 * Adds a <code>Criterion</code> conditional statement to this
		 * <code>Criteria</code> instance to be evaluated against 
		 * each object in this instance's <code>SearchProvider</code>.
		 * If <code>value.evaluate(instance)</code> returns false, 
		 * <code>instance</code> will not be included in the results.
		 * @param	value	A <code>Criterion</code> instance to be run against each object
		 * 		in the <code>SearchProvider</code> collection.
		 * @return Returns this instance for method chaining.
		 * 
		 * @see org.as3search.criteria.Criterion
		 * @see org.as3search.criteria.Restrictions
		 * @see org.as3search.providers.SearchProvider
		 */
		function add(value:Criterion):Criteria;
		/**
		 * Creates a new <code>Criteria</code> instance targeting a subcollection
		 * on each item in this <code>Criteria</code> instance's collection. What 
		 * this means is that for each item in the master collection, the <code>
		 * criterion</code> object will be executed on each member of the item's
		 * subcollection property specified by <code>propertyName</code>. 
		 * 
		 * @example Let's pretend you're looking for a user who's a friend with
		 * another user. This example demonstrates how you would search for that user:
		 * <listing version="3.0">
		 * var collection:Array = [{id: 0, friends: [{id: 1}]}, 
		 * 	{id: 1, friends: [{id: 0}]}];
		 * var results:Array = Search.within(collection)
		 * 		.add(Restrictions.ne("id", 0))
		 * 		.createCriteria("friends", Restrictions.conjunction()
		 * 			.add(Restrictions.eq("id", 0)))
		 * 		.list();
		 * </listing> 
		 * First, we add a condition to make sure we don't select user #0. Then
		 * with a call to <code>createCriteria()</code>, we create a restriction
		 * on items in the "friends" subcollection, making sure that each item 
		 * in <code>collection</code> has at least one subitem under "friends" that
		 * has an id of 0. Thus, we have found a user which does not have the id of
		 * 0 and has a friend within "friends" that does have the id of 0. 
		 * 
		 * @param	propertyName	The collection property of each object in the master
		 * 		collection.
		 * @param	criterion		The <code>Criterion</code> instance to run against each
		 * 		item in the subcollection specified by <code>propertyName</code>.
		 * @return Returns this instance for method chaining.
		 * 
		 * @see org.as3search.criteria.SubCriteria
		 */
		function createCriteria(propertyName:String, criterion:Criterion):Criteria;
		/**
		 * Evaluates all of the <code>Criterion</code> instances added against each 
		 * member of the collection until a match is found and returned.
		 * 
		 * @return Returns null if no item could be found, or the first item to match all of the given
		 * 		<code>Criterion</code> conditions.
		 */
		function uniqueResult():Object;
		/**
		 * Evaluates all of the <code>Criterion</code> instances added against each
		 * member of the collection and returns all collection members that 
		 * match the conditions.
		 * 
		 * @return Returns an <code>Array</code> of all of the matching items in the 
		 * 		master collection.
		 */
		function list():Array;
		/**
		 * "Tests" and makes sure that at least one item in the master collection
		 * matches the <code>Criterion</code> instances within this <code>Criteria</code>.
		 * Great for you asserters out there :)
		 * 
		 * @return Returns true if at least one item matches the conditions, false otherwise.
		 */
		function test():Boolean;
		/**
		 * The <code>SearchConfiguration</code> for this <code>Criteria</code> instance.
		 * The <code>SearchConfiguration</code> governs how this <code>Criteria</code>
		 * deals with <code>Criterion</code> instances, resolution of properties, and
		 * resolution of collections.
		 * 
		 * @see org.as3search.config.SearchConfiguration
		 */
		function get configuration():SearchConfiguration;
	}
}